import { Socket } from 'socket.io';
import subscribe from './subscribe';
import unsubscribe from './unsubscribe';
import disconnect from './disconnect';
import message from './message';
import notice from './notice';
import { middlewares } from './middlewares';
// import connection from './connection';
import WebRTCServer from '../webrtc';
import { Member } from "../lib/Member";
import {ChatModeEnums, InviteModeEnums, JoinModeEnums, RoomTypeEnums} from "../utils/enums";
import {Room} from "../lib/Rooms";
// import {SocketId} from "socket.io-adapter";

const classType = RoomTypeEnums.RESIDENT;
const inviteMode = InviteModeEnums.NO_VERIFY;
const joinMode = JoinModeEnums.NO_VERIFY;
const chatMode = ChatModeEnums.GROUP;

interface queryTypes {
  [key: string]: string
}

export default function runWebSocketServer (app) {
  const { io, rooms: lRoom } = app.locals;
  const intercom = io.of('/intercom');
  app.locals.intercom = intercom;

  // webSocket
  intercom.on('connection', function (socket: Socket) {
    // const url = socket.request.headers.referer;
    const query = socket.handshake.query as queryTypes;
    const { classId, classname, userId, username } = query;
    const roomOption = {
      classId, classname, classType, inviteMode, joinMode, chatMode
    };
    const owner = (
      (socket as any).owner = { userId, username, socketId: socket.id }
    );

    app.locals.socket = socket;

    function connection () {
      const __owner = Member.createMember(owner);

      // 加入 常驻房间
      socket.join(classId);
      // 储存常驻房间用户列表
      if (!lRoom[classId]) {
        lRoom[classId] = new Room(roomOption)
      }

      lRoom[classId].setMember(__owner);
      intercom[userId] = socket

      // 中间件
      middlewares(socket)

      // 客户端的send方法发送的消息
      message(app);

      // WebRTC 服务
      WebRTCServer(app);

      // 通知指定 userId 的用户
      notice(app);

      // 订阅
      subscribe(app);

      // 退订
      unsubscribe(app);

      // 断开连接
      disconnect(app);
    }

    /**
     * 登陆时判断用户是否重复登陆。
     * 如果重复登陆，则让用户选择，是放弃，还是强制登陆。
     */
    if (app.locals.members[userId]) {
      const repeatOption = {
        status: 'error',
        message: 'Repeat login'
      }

      /**
       * 等待 3 分钟
       * 用户重复登陆，是放弃登陆，还是将对方挤下去。
       * 让用户自己决定
       * 如果用户不决定，那么默认会登陆失败，将用户 socket 断掉。
       * 客户端可以设置 3 分钟之内的其他时间长度，断掉连接。
       *
       * let exec;
       * socket.on('repeat', (data, callback) => {
       *   exec = function () {
       *     callback()
       *     callback = null
       *   }
       *   setTimeout(() => {
       *     if (callback) callback(false)
       *   }, 1000 * 60)
       * })
       */
      socket
        .timeout(1000 * 10)
        .emit('repeat', repeatOption, (error) => {
        if (error) {
          socket.emit('error', {
            status: 'error',
            message: 'Repeat login'
          })
          socket.disconnect()
        } else {
          // 通知已登陆角色，有人将他挤掉线。
          // 将已登陆角色下线，然后使用当前新的socket重新建立连接
          // 等待 300 毫秒，保证信息发给了用户。
          // 用户收到信息，是要现实被挤下线的弹出框的，
          app
            .locals
            .sockets[userId]
            .timeout(300)
            .emit('error', {
              status: 'error',
              message: 'Repeat login'
            }, () => {
            app.locals.sockets[userId].disconnect()
            connection()
          })
        }
      })
    } else {
      connection()
    }

    console.log('connection')
    // Join room
    // Exit room
  });

  io.on('leave', function () {
    console.log('-----------');
    io.emit('disconnect');
  });
}
